﻿namespace FML

#light
     
#if INTERACTIVE
#I @"C:\Program Files\Reference Assemblies\Microsoft\F#\1.0\Runtime\v2.0"
#I @"C:\Windows\Microsoft.NET\Framework\v2.0.50727"
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5"

#r "mscorlib.dll"
#r "System.dll"
#r "System.Core.dll"
#r "C:\Users\jcm\Documents\projects\Monads\libs\FsCheck.dll"
#r "C:\Users\jcm\Documents\projects\Monads\libs\NunitCore.dll"
#r "C:\Users\jcm\Documents\projects\FML\FML\obj\Debug\Monads.dll"
#endif

module ReaderT =

 printf "Reader trans test\n\n"

 module Option = 

  open ReaderT.Option
  open ReaderM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = readerOptionT.Bind (m, f)
  let ret = readerOptionT.Return


  quickCheck (fun  f a env-> run ((ret a) >>= f) env = run (f a) env )
  quickCheck (fun m env -> run (m >>= ret) env = run m env)
  quickCheck (fun m f g env -> run ((m >>= f) >>= g) env = run (m >>= (fun x -> f x >>= g)) env)

 module List = 

  open ReaderT.List
  open ListM
  open ReaderM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = readerListT.Bind (m, f)
  let ret = readerListT.Return

 
  quickCheck (fun  f a env-> run ((ret a) >>= f) env = run (f a) env )
  quickCheck (fun m env -> run (m >>= ret) env = run m env)
  quickCheck (fun m f g env -> run ((m >>= f) >>= g) env = run (m >>= (fun x -> f x >>= g)) env)

 module State = 

  open ReaderT.State
  open StateM
  open ReaderM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = readerStateT.Bind (m, f)
  let ret = readerStateT.Return

  let runR  = ReaderM.run
  let runS = StateM.run

 
  quickCheck (fun  f a env s-> runS (runR ((ret a) >>= f) env) s = runS (runR (f a) env) s )
  quickCheck (fun m env s -> runS (runR (m >>= ret) env ) s = runS (runR m env) s)
  quickCheck (fun m f g env s -> runS ( runR ((m >>= f) >>= g) env ) s = runS (runR (m >>= (fun x -> f x >>= g)) env ) s)

 module Error = 

  open ReaderT.Error
  open ErrorM
  open ReaderM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = readerErrorT.Bind (m, f)
  let ret = readerErrorT.Return

 
  quickCheck (fun  f a env->  run ((ret a) >>= f) env  =  run (f a) env  )
  quickCheck (fun m env -> run (m >>= ret) env = run m env)
  quickCheck (fun m f g env -> run ((m >>= f) >>= g) env = run (m >>= (fun x -> f x >>= g)) env)

 module Writer = 

  open ReaderT.Writer
  open ReaderM
  open WriterM
  open Monoid

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck
  
  let monoid = new ListMonoid<int>() :> Monoid<int list>

  let writerM = WriterBuilder<int list>(monoid) :> IWriterMonad<int list>

  let readerWriterT = new ReaderWriterBuilder<int list>(writerM) :> IReaderWriterTrans<int list>
  
  let (>>=) m f = readerWriterT.Bind (m, f)
  let ret = readerWriterT.Return

  let runR = ReaderM.run
  
  quickCheck (fun  f a env -> (runR ((ret a) >>= f) env) =  (runR (f a) env) )
  quickCheck (fun m env -> runR (m >>= ret) env = runR m env)
  quickCheck (fun m f g env -> runR ((m >>= f) >>= g) env = runR (m >>= (fun x -> f x >>= g)) env)

